<?php

namespace app\rabbitmq\controller;

use app\common\cachemodel\AppConfig;
use app\common\lib\Push;
use app\common\lib\Rectification;
use app\common\model\MessageCenter;
use app\common\model\Orders;
use PhpAmqpLib\Connection\AMQPStreamConnection;
use think\Controller;
use app\common\model\Rectification as RectificationModel;
use think\Db;

error_reporting(0);

class RectificationConsumer extends Controller
{

    public function stop($channel, $connection)
    {
        $channel->close();
        $connection->close();
    }

    public function start()
    {

        $connection = new AMQPStreamConnection(config('rabbitmq.host'), config('rabbitmq.port'), config('rabbitmq.username'), config('rabbitmq.password'));
        $channel = $connection->channel();

        $channel->exchange_declare('delay_rectification_exchange', 'direct', false, false, false);
        $channel->exchange_declare('rectification_exchange', 'direct', false, false, false);

        $channel->queue_declare('delay_rectification_queue', false, true, false, false, false);
        $channel->queue_bind('delay_rectification_queue', 'delay_rectification_exchange', 'delay_rectification_exchange');

        print(' 监听Rabbitmq 校准生辰消息队列... ');

        //只有consumer已经处理并确认了上一条message时queue才分派新的message给它
        $channel->basic_qos(null, 1, null);
        $channel->basic_consume('delay_rectification_queue', '', false, false, false, false, array($this, 'startRectificationTask'));

        register_shutdown_function(array($this, 'stop'), $channel, $connection);

        while (count($channel->callbacks))
        {
            $channel->wait();
        }


    }

    function startRectificationTask($msg)
    {

        print(date('Y-m-d H:i:s') . " [x] 接收到消息" . $msg->body);
        $data = json_decode($msg->body, true);

        print("校准生辰开始时间 " . date('Y-m-d H:i:s') . "\n");
        \think\Log::write('校准生辰开始时间:' . date('Y-m-d H:i:s'), 'log', true);
        // \think\Log::write('校准生辰数据:'.var_export($data,true),'log',true);
        // 总共执行次数  最多120次（每分钟一个星盘）
        $OrdersModel = new Orders();
        $n = ceil($data['end_time'] - $data['start_time']) / 60;
        $events = [];
        for ($i = 0; $i < $n; $i++)
        {
            // 每分钟一个
            $birth_time = $data['start_time'] + $i * 60;
            $events[date('Y-m-d H:i', $birth_time)] = (new Rectification())->getValidEventsScore($data['events'], $birth_time, $data['recode']);
        }

        $events = array_filter($events);

        $reid = $data['reid'];

        $status = 2;
        $result_all = [];

        if (empty($events))
        {
            print("校准生辰失败时间 " . date('Y-m-d H:i:s') . "\n");
            \think\Log::write('校准生辰失败时间:' . date('Y-m-d H:i:s'), 'log', true);

            $status = 3;
        } else
        {
            array_multisort($events, SORT_NUMERIC, SORT_DESC);

            $result = array_slice($events, 0, 3, true);

            // 两个原则：1，优先接近用户原本时间的结果；
            // 2，优先与用户原上升星座相同的结果
            // 如果最高得分满足与原上升相同且在差距不超过十分钟这个条件，定位最佳结果，
            // 如果有多个，则最接近原时间的是最佳结果。
            // 如果最高得分不同时满足以上条件，优先在十分钟之内的，
            // 如没有则选择同上升的。同上升条件下选择更接近原时间的。

            // 统计各值在数组中出现的次数
            // $count_result = array_count_values($events);

            // \think\Log::write('校准生辰结果统计:'. var_export($count_result,true),'log',true);


            $n = 0;
            foreach ($result as $k => $r)
            {
                if ($n == 1) $r--;
                elseif ($n == 2) $r -= 2;
                $result_all[] = ['time' => strtotime($k), 'score' => $r];
                $n++;
            }

            \think\Log::write('校准生辰结果:' . var_export($result, true), 'log', true);
            print("校准生辰结果: " . var_export($result, true) . "\n");
//            \think\Log::write('任务执行次数:'.$job->attempts(),'log',true);
//            print("任务执行次数：".$job->attempts()."\n");
            \think\Log::write('校准生辰结束时间:' . date('Y-m-d H:i:s'), 'log', true);
            print("校准生辰结束时间 " . date('Y-m-d H:i:s') . "\n");
        }

        try
        {
            $rectification = RectificationModel::get($reid);
            $rectification->isUpdate(true)->save(['status' => $status, 'result_time' => time()]);
//            $OrdersModel->isUpdate(true)->save(['status' => 4], ['id' => $data['oid']]);

            if (!empty($result_all))
            {
                $rectification->result()->where('reid', $reid)->delete();// 先删再存
                $rectification->result()->saveAll($result_all);
            }
        }
        catch (\Exception $e)
        {
            print("校准生辰结果入库失败 " . $e->getMessage() . "\n");
            \think\Log::write('校准生辰结果入库失败:' . $e->getMessage(), 'log', true);
            $rectification = RectificationModel::get($reid);
            $rectification->isUpdate(true)->save(['status' => 3]);
//            $OrdersModel->isUpdate(true)->save(['status' => 5], ['id' => $data['oid']]);

        }

        $user = Db::table('wechat_backup_07_18_14_43_00.app_user')->field('id,regid,tel')->where('id', $rectification['uid'])->find();
        // APP推送
        // if($user && $user['regid'] != '')
        // {
        //     print("开始推送:" . var_export($user,true) ."\n");
        //     \think\Log::write('开始推送：'. var_export($user,true),'log',true);
        //     (new Push())->pushSpecial($user['regid'],'您提交的校准生辰已经完成了，点击查看校正结果！',['action'=>'rectification_details','id'=>$reid]);
        // }
        print("开始推送:" . var_export($user, true) . "\n");
        \think\Log::write('开始推送：' . var_export($user, true), 'log', true);
        $pushRes = (new Push())->pushUserMsg($user['id'], '您提交的校准生辰已经完成了，点击查看校正结果！', ['action' => 'rectification_details', 'id' => $reid]);
        if (!$pushRes['success'])
        {
            print("校准生辰完成->推送失败" . PHP_EOL);
            \think\Log::write("校准生辰完成->推送失败: " . PHP_EOL . var_export($pushRes['message'], true) . PHP_EOL, 'error', true);
        }
        // 短信通知
        if ($user && $user['tel'] != '')
        {
            print("短信通知:" . var_export($user, true) . "\n");
            \think\Log::write('短信通知：' . var_export($user, true), 'log', true);
            $alidayu = (new AppConfig())->configInfo('alidayu');
            sendSms($user['tel'], [], $alidayu['rectification_code']);
        }

        //消息中心添加信息
        $data = [
            'status' => 0,
            'is_read' => 0,
            'range' => $user['id'],
            'type' => 2,
            'cid' => 1,
            'reid' => $reid,
            'title' => '校准生辰结果',
            'content' => '您提交的校准生辰已经完成了，点击查看校正结果！',
            'link' => 'rectification_details?id=' . $reid . '&need_auth=1',
            'target' => "local",
            'create_time' => time()
        ];
        //添加消息
        (new MessageCenter())->pushMessage($user['id'], $data);
        //确认收到消息
        $msg->delivery_info['channel']->basic_ack($msg->delivery_info['delivery_tag']);
    }


}

